<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="root">
  </div>
  <script>
    // 1、Plugin名称  
  const MY_PLUGIN_NAME = "MyBasicPlugin";  
  
  class MyBasicPlugin {  
    // 2、在构造函数中获取插件配置项  
    constructor(option) {  
      this.option = option;  
    }  
    
    // 3、在原型对象上定义一个apply函数供webpack调用  
    apply(compiler) {  
      // 4、注册webpack事件监听函数  
      compiler.hooks.emit.tapAsync(  
        MY_PLUGIN_NAME,  
        (compilation, asyncCallback) => {  
    
          // 5、操作Or改变compilation内部数据  
          console.log(compilation);        
    
          console.log("当前阶段 ======> 编译完成，即将输出到output目录");  
    
          // 6、如果是异步钩子，结束后需要执行异步回调  
          asyncCallback();  
        }  
      );  
    }  
  }   
  // 7、模块导出  
  module.exports = MyBasicPlugin;

  // 导出一个函数，source为webpack传递给loader的文件源内容
module.exports = function(source) {
    const content = doSomeThing2JsString(source);
    
    // 如果 loader 配置了 options 对象，那么this.query将指向 options
    const options = this.query;
    
    // 可以用作解析其他模块路径的上下文
    console.log('this.context');
    
    /*
     * this.callback 参数：
     * error：Error | null，当 loader 出错时向外抛出一个 error
     * content：String | Buffer，经过 loader 编译后需要导出的内容
     * sourceMap：为方便调试生成的编译后内容的 source map
     * ast：本次编译生成的 AST 静态语法树，之后执行的 loader 可以直接使用这个 AST，
     * 进而省去重复生成 AST 的过程
     */
    this.callback(null, content); // 异步
    return content; // 同步
}
  </script>
</body>

</html>